package com.pennphoto.client;

import java.util.ArrayList;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONNumber;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONString;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.xml.client.Document;
import com.google.gwt.xml.client.Node;
import com.google.gwt.xml.client.XMLParser;
import com.google.gwt.user.client.ui.DockLayoutPanel;
import com.google.gwt.dom.client.Style.Unit;

/**
 * This is the main class for generating visual results for CIS 550 HW4
 * 
 * @author zives
 *
 */
public class PennPhoto implements EntryPoint {
	/**
	 * The message displayed to the user when the server cannot be reached or
	 * returns an error.
	 */
	private int userid;
	private Grid grid;
	private VerticalPanel info;
	private Button next, previous;
	public PennPhoto(int uid){
		userid=uid;
	}
	
	private static final String SERVER_ERROR = "An error occurred while "
			+ "attempting to contact the server. Please check your network "
			+ "connection and try again.";

	/**
	 * Create a remote service proxy to talk to the server-side service.
	 */
	private final QueryXMLAsync queryService = GWT
			.create(QueryXML.class);

	/**
	 * This contains the XML content pasted by the user into the text area
	 */
	
	
	/**
	 * This is the ID of the person highlighted by the user
	 */
	private int currentPerson;
	
	/**
	 * This is the graph visualization as an object
	 */
	private JavaScriptObject theGraph;
	private JavaScriptObject theGraph2;
	
	/**
	 * This is the maximum number of photos to be displayed
	 */
	private final static int photoCount = 10;
	private int firstPhoto = 0;
	
	/**
	 * This is the entry point method.
	 */
	final ArrayList<Integer> friends = new ArrayList<Integer>();
	@Override
	public void onModuleLoad( ) {
		// Set up the photo grid on the left side
		AbsolutePanel ap = new AbsolutePanel();
		final RootPanel rootPanel = RootPanel.get();
		DockLayoutPanel dockLayoutPanel = new DockLayoutPanel(Unit.EM);
		rootPanel.add(dockLayoutPanel, 105, 78);
		dockLayoutPanel.setSize("80%", "80%");
		
		grid = new Grid(photoCount+1, 1);
		dockLayoutPanel.addEast(grid, 10.0);
		grid.setSize("200", "236");
		
		HorizontalPanel horizontalPanel = new HorizontalPanel();
		grid.setWidget(10, 0, horizontalPanel);
		
		next = new Button("Next");
		horizontalPanel.add(next);
		
		previous = new Button("Previous");
		horizontalPanel.add(previous);
		
		info = new VerticalPanel();
		dockLayoutPanel.addWest(info, 10);
		
		Button homePage = new Button("Home Page");
		rootPanel.add(homePage,600,1);
		
		HTML html = new HTML("<div id='infovis'></div>", true);
		html.setStyleName("#infovis");
		dockLayoutPanel.add(html);

		previous.setEnabled(false);
		next.addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				requestNextPhotoPage(); 
			}
			
		});
		
		previous.addClickHandler(new ClickHandler(){
			@Override
			public void onClick(ClickEvent event){
				requestPreviousPhotoPage();
			}
		});
		
		homePage.addClickHandler(new ClickHandler(){
			@Override
			public void onClick(ClickEvent event){
				rootPanel.clear();
				UserProfile u = new UserProfile(userid);
				u.onModuleLoad();
				History.newItem("");
			}
		});
		
		
		try {
			visualizeInitialPerson();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
		
	}
	
	/**
	 * Request the ID of the first person in the data, then visualize him/her
	 * @throws Exception 
	 * @throws IllegalArgumentException 
	 * 
	 */
	public void visualizeInitialPerson() throws IllegalArgumentException, Exception {
				
				int person;
				currentPerson=userid;
				person = currentPerson;
				queryService.getFriends(person, new AsyncCallback<ArrayList<Integer>>(){
					@Override
					public void onFailure(Throwable caught){
						System.out.println("Failed");
					}
					
					@Override 
					public void onSuccess(ArrayList<Integer> result){
						try{
							for ( int i = 0; i < result.size();i++){
								friends.add(result.get(i));
							}
						}catch(Exception e){
							e.printStackTrace();
						}
						
					}
				});
				
				queryService.getPersonAndNeighbors( person, new AsyncCallback<String>() {
				
					@Override
					public void onFailure(Throwable caught) {
						Window.alert("Unable to execute XQuery");
						
					}

					@Override
					public void onSuccess(String result) {
						try {
							JSONObject x = XMLandJSON.getJsonForUser(XMLandJSON.parseXML(result));
							if (x != null) {
								System.out.println(x.toString());
								
								theGraph = FriendVisualization.createGraph(x.toString(), PennPhoto.this);
								//theGraph2 = FriendVisualization.createGraph(x.toString(), PennPhoto.this);
							}
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
				});
				
				// Request the person's photos
				loadPhotos();
				displayUserContent();
				
			}
			
		/*});/*
	}
	
	/** 
	 * Load up to the max # of photos into the grid on the right-hand side of
	 * the screen.
	 *   
	 * @param person
	 */
	 public void loadPhotos() {
		// Request photos
		queryService.getPhotos(currentPerson, firstPhoto, photoCount, new AsyncCallback<String>() {

			@Override
			public void onFailure(Throwable caught) {
				Window.alert(SERVER_ERROR);
			}

			@Override
			public void onSuccess(String result) {
				for (int i = 0; i < photoCount; i++)
					grid.clearCell(i, 0);
				
				Node n = XMLandJSON.parseXML(result);
				System.out.println(n.toString());

				// Iterate through photos and place them in the grid.
				// Warning: Will crash if there are too many photos.  Hence make sure
				// there never are too many!
				int i = 0;
				if (n != null)
					for (Node child = n.getFirstChild(); child != null; child = child.getNextSibling()) {
						if (child.getNodeName().equals("photo")) {
							for (Node content = child.getFirstChild(); content != null; content = content.getNextSibling()) {
								if (content.getNodeName().equals("url")) {
									System.out.println(child.toString());
									grid.setHTML(i, 0, "<img src='" + XMLandJSON.getTextNode(content) + "'width='200' height='150'/>");
									i++;
								}
							}
						}
					}
			}
			
		});
	} 

	/**
	 * Incrementally redraw graph for the selected person.
	 * Also update the left and right-hand panes
	 * 
	 * @param result
	 */
	public void drawNodeAndNeighbors(int person) {
		currentPerson = person;
		firstPhoto = 0;
		System.out.println("Requesting data for " + person);
		if ( friends.contains(person)){
		queryService.getPersonAndNeighbors( person, new AsyncCallback<String>() {

			@Override
			public void onFailure(Throwable caught) {
				Window.alert(SERVER_ERROR);
				
			}

			@Override
			public void onSuccess(String result) {
				Node n = XMLandJSON.parseXML(result);
				
				if (n != null) {
					FriendVisualization.addToGraph(theGraph, XMLandJSON.getJsonForUser(n).toString());
					
				}
			}
		
		});
		}
		loadPhotos();
		displayUserContent();
		
	}

	
	/**
	 * TODO Update the info pane with the user's age, gender, class (prof, student, etc.), and
	 * so on
	 */
	public void displayUserContent() {
		queryService.getPersonAndNeighbors(currentPerson, new AsyncCallback<String>(){
			@Override
			public void onFailure(Throwable caught) {
				Window.alert(SERVER_ERROR);
			}
			@Override
			public void onSuccess(String result){
				info.clear();		
				Node n = XMLandJSON.parseXML(result);
				info.add(new Label("--"));
				info.add(new Label("User type:"+n.getNodeName()));
				for (Node content = n.getFirstChild();content != null; content=content.getNextSibling()){
					if ( content.getNodeName().equals("id"))
						info.add(new Label("ID:"+content.getFirstChild().getNodeValue()));
					if ( content.getNodeName().equals("name"))
						info.add(new Label("Name:"+content.getFirstChild().getNodeValue()));
					if ( content.getNodeName().equals("email"))
						info.add(new Label("Email:"+content.getFirstChild().getNodeValue()));
					if ( content.getNodeName().equals("age"))
						info.add(new Label("age:"+content.getFirstChild().getNodeValue()));
				}
				
			}
		});
	}
	public void requestNextPhotoPage() {
		 firstPhoto+=photoCount;
		 loadPhotos();
		 if(firstPhoto>1){
			 previous.setEnabled(true);
		 }
		 if (firstPhoto >= 10){
				next.setEnabled(false);
			}
			
				
	}
	
	
	public void requestPreviousPhotoPage(){
		
		firstPhoto-=photoCount;
		loadPhotos();
		if (firstPhoto<=0){
			previous.setEnabled(false);
		}
		if (firstPhoto < 20){
			next.setEnabled(true);
		}
		
	}
}
